#ifndef _MEM_POOL_H_
#define _MEM_POOL_H_

#include "locker.h"
#include "list.h"
#include "def.h"

#ifdef __cplusplus
extern "C"{
#endif

typedef struct mem_unit mem_unit_t;
typedef struct mem_pool mem_pool_t;

struct mem_unit
{
	uint32_t total;
    uint32_t size;
	void *(*create)(mem_unit_t *); // create memory unit
	int (*destroy)(mem_unit_t *, void *); // destroy memory unit
	void (*release)(mem_unit_t *); // release itself
    void *priv; 
};

/******************************************************************************
*                 general memory unit context
*****************************************************************************/
inline static void *mem_unit_generic_create(mem_unit_t *self)
{
	return MALLOC(self->size);
}

inline static int mem_unit_generic_destroy(mem_unit_t *self, void *ptr)
{
	safe_free(ptr);
	return 0;
}

#if 0
static mem_unit_t g_mem_unit = {
	.create = mem_unit_generic_create,
	.destroy = mem_unit_generic_destroy,
	.release = NULL,
	.priv = NULL,
};
#endif

struct mem_pool
{
    struct dl_list list;
    uint32_t unit_nums;
    mem_unit_t *mu;
    locker_t *locker;
};

int mem_pool_init(mem_pool_t *self, locker_t *locker);
void mem_pool_term(mem_pool_t *self);

void *mem_unit_get(mem_pool_t *self);
int mem_unit_put(mem_pool_t *self, void *ptr);

static inline mem_pool_t *mem_pool_create(locker_t *locker, mem_unit_t *mu)
{
	if (!mu || !mu->create || !mu->destroy) {
		DBG("invalid args");
		return NULL;
	}

	mem_pool_t *self = (mem_pool_t *)MALLOC(sizeof(mem_pool_t));
	if(self){
		self->mu = mu;
		
		if (mem_pool_init(self, locker) < 0)
			safe_free(self);
	}

	return self;
}

static inline void mem_pool_destroy(mem_pool_t **p_self)
{
	if(p_self && *p_self){
		mem_pool_term(*p_self);
		safe_free(*p_self);
	}
}

static inline uint32_t mem_unit_size(mem_pool_t *self)
{
//	return mp_get_mu_size(self);
	return self->mu->size;
}

static inline uint32_t mem_unit_nums(mem_pool_t *self)
{
	return self->unit_nums;
}


#ifdef __cplusplus
}
#endif // end __cplusplus

#endif // end _MEM_POOL_H_
